@codeyam/codeyam-cli 0.1.20 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +1 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +36 -9
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
- package/analyzer-template/packages/analyze/index.ts +4 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
- package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +4 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +4 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +235 -58
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +170 -26
- package/analyzer-template/packages/aws/package.json +1 -1
- package/analyzer-template/packages/database/src/lib/loadEntity.ts +11 -4
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts +4 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js +4 -4
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts +3 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +22 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +27 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +63 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +553 -93
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +991 -31
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +11 -3
- package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +33 -1
- package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
- package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js +127 -0
- package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js +217 -0
- package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
- package/codeyam-cli/src/utils/analysisRunner.js +28 -1
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/analyzer.js +11 -1
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +210 -14
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorPreview.js +5 -3
- package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
- package/codeyam-cli/src/utils/entityChangeStatus.server.js +16 -0
- package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -1
- package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
- package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
- package/codeyam-cli/src/utils/queue/job.js +20 -2
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/registerScenarioResult.js +52 -0
- package/codeyam-cli/src/utils/registerScenarioResult.js.map +1 -0
- package/codeyam-cli/src/utils/testRunner.js +199 -1
- package/codeyam-cli/src/utils/testRunner.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +35 -0
- package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js +3 -0
- package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-CQENLSrF.js +36 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-scenario-data-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-schema-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CCKUIm0S.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-aIHKLB-m.js +96 -0
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-CluPkvXJ.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-Blfy9UlN.js → entity._sha._-ByHz6rAQ.js} +13 -12
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-KTQuL0aj.js → entity._sha.scenarios._scenarioId.dev-CmLO432x.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-C6eeL24i.js → entity._sha.scenarios._scenarioId.fullscreen-Bz9sCUF_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-oyPmV37k.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-bcbb3d49.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{root-BxUQigda.js → root-D2_tktnk.js} +26 -13
- package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-DjF-soOH.js +16 -0
- package/codeyam-cli/src/webserver/build/server/assets/{index-CjLhfz6Z.js → index-nAvHGWbz.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-BEqlbI84.js → init-XhpIt-OT.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DVwiibFu.js +644 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/idleDetector.js +15 -0
- package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +18 -5
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +2 -2
- package/package.json +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +27 -10
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/analyze/index.js +1 -1
- package/packages/analyze/index.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +1 -0
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
- package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeChange.js +1 -0
- package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeInitial.js +1 -0
- package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
- package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +116 -28
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +139 -24
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/database/src/lib/loadEntity.js +4 -4
- package/packages/database/src/lib/loadEntity.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +22 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DII1pg_z.js +0 -58
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-oepecPae.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/globals-Yn9W3zp3.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-cdf2c0a7.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-B_PsTAb1.js +0 -13
- package/codeyam-cli/src/webserver/build/server/assets/server-build-YI63xTu4.js +0 -553
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-03-24T14:27:03.288Z",
|
|
3
|
+
"buildTime": 1774362423288,
|
|
4
|
+
"gitCommit": "af072353c0de778f2916c445dec0ca98b1ee7180",
|
|
5
5
|
"nodeVersion": "v20.20.1",
|
|
6
|
-
"contentHash": "
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
6
|
+
"contentHash": "2352c3294573a7af51e18b678f86299d7a1fe24cbf8427cdfcd4472c2f613df6",
|
|
7
|
+
"buildNumber": 1216,
|
|
8
|
+
"semanticVersion": "0.1.1216",
|
|
9
|
+
"version": "0.1.1216 (2026-03-24T14:27+2352c32)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[3/
|
|
3
|
-
[3/
|
|
2
|
+
[3/24/2026, 2:27:03 PM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[3/24/2026, 2:27:03 PM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[3/
|
|
6
|
+
[3/24/2026, 2:27:03 PM] Merged dependencies into root package.json
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@aws-sdk/client-cloudwatch-logs": "^3.990.0",
|
|
11
11
|
"@aws-sdk/client-cloudfront": "^3.990.0",
|
|
12
|
-
"@aws-sdk/client-codebuild": "^3.
|
|
12
|
+
"@aws-sdk/client-codebuild": "^3.1014.0",
|
|
13
13
|
"@aws-sdk/client-dynamodb": "^3.990.0",
|
|
14
14
|
"@aws-sdk/client-ec2": "^3.990.0",
|
|
15
15
|
"@aws-sdk/client-ecr": "^3.990.0",
|
|
@@ -398,6 +398,7 @@ const SILENTLY_IGNORED_EQUIVALENCY_REASONS = new Set([
|
|
|
398
398
|
'transformed non-object function equivalency - Array.from() equivalency',
|
|
399
399
|
'Spread operator equivalency key update: Explicit array deconstruction equivalency value',
|
|
400
400
|
// 'transformed non-object function equivalency - Explicit array deconstruction equivalency value',
|
|
401
|
+
'useState setter call equivalency (direct)',
|
|
401
402
|
]);
|
|
402
403
|
|
|
403
404
|
export class ScopeDataStructure {
|
|
@@ -1048,9 +1049,38 @@ export class ScopeDataStructure {
|
|
|
1048
1049
|
equivalencyValueChain?: EquivalencyValueChainItem[],
|
|
1049
1050
|
traceId?: number,
|
|
1050
1051
|
) {
|
|
1052
|
+
// Fast early exits that don't count toward the limit.
|
|
1053
|
+
// These are "no-op" calls that would be caught further below anyway,
|
|
1054
|
+
// but checking them first prevents counter inflation from redundant calls
|
|
1055
|
+
// generated by managers and followEquivalencies during scope processing.
|
|
1056
|
+
|
|
1057
|
+
// Skip silently-ignored reasons before counting
|
|
1058
|
+
if (SILENTLY_IGNORED_EQUIVALENCY_REASONS.has(equivalencyReason)) {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// Skip exact duplicates before counting (Phase 1 only — Phase 2 needs
|
|
1063
|
+
// to process duplicates for database chain tracking)
|
|
1064
|
+
if (this.onlyEquivalencies) {
|
|
1065
|
+
const existing = scopeNode.equivalencies[path];
|
|
1066
|
+
if (
|
|
1067
|
+
existing?.some(
|
|
1068
|
+
(v) =>
|
|
1069
|
+
v.schemaPath === equivalentPath &&
|
|
1070
|
+
v.scopeNodeName === equivalentScopeName,
|
|
1071
|
+
)
|
|
1072
|
+
) {
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1051
1077
|
addEquivalencyCallCount++;
|
|
1052
1078
|
|
|
1053
|
-
|
|
1079
|
+
const limit =
|
|
1080
|
+
typeof (globalThis as any).__CODEYAM_EQUIVALENCY_LIMIT === 'number'
|
|
1081
|
+
? (globalThis as any).__CODEYAM_EQUIVALENCY_LIMIT
|
|
1082
|
+
: 50000;
|
|
1083
|
+
if (addEquivalencyCallCount > limit) {
|
|
1054
1084
|
console.error('INFINITE LOOP DETECTED in addEquivalency', {
|
|
1055
1085
|
callCount: addEquivalencyCallCount,
|
|
1056
1086
|
path,
|
|
@@ -1065,14 +1095,11 @@ export class ScopeDataStructure {
|
|
|
1065
1095
|
}
|
|
1066
1096
|
// Filter equivalency reasons - use pre-computed Sets for O(1) lookup
|
|
1067
1097
|
if (!ALLOWED_EQUIVALENCY_REASONS.has(equivalencyReason)) {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
console.info('Not tracked equivalency reason', { equivalencyReason });
|
|
1074
|
-
return;
|
|
1075
|
-
}
|
|
1098
|
+
// Silently-ignored reasons already handled above
|
|
1099
|
+
// Log and skip - if an equivalency reason isn't in ALLOWED or SILENTLY_IGNORED,
|
|
1100
|
+
// it shouldn't be stored (was previously missing the return)
|
|
1101
|
+
console.info('Not tracked equivalency reason', { equivalencyReason });
|
|
1102
|
+
return;
|
|
1076
1103
|
}
|
|
1077
1104
|
|
|
1078
1105
|
// Skip self-referential equivalencies that would create infinite loops.
|
|
@@ -97,6 +97,16 @@ export default class ParentScopeManager implements EquivalencyManager {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
if (instantiatedInParent || returnValueFromChildScope) {
|
|
100
|
+
// Skip if we've already propagated this variable to the parent scope.
|
|
101
|
+
// Without this guard, nested scopes trigger redundant addEquivalency calls
|
|
102
|
+
// for the same variable on every addToSchema pass (e.g., 'a' and 'b' in sort
|
|
103
|
+
// callbacks get propagated 30+ times per scope instead of once).
|
|
104
|
+
this.addedToParent[scopeNode.name] ||= new Set<string>();
|
|
105
|
+
if (this.addedToParent[scopeNode.name].has(rootPath)) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
this.addedToParent[scopeNode.name].add(rootPath);
|
|
109
|
+
|
|
100
110
|
if (traceId && debugLevel > 0) {
|
|
101
111
|
console.info(
|
|
102
112
|
'Debug Propagation: parentScope executed',
|
|
@@ -114,9 +124,6 @@ export default class ParentScopeManager implements EquivalencyManager {
|
|
|
114
124
|
);
|
|
115
125
|
}
|
|
116
126
|
|
|
117
|
-
this.addedToParent[scopeNode.name] ||= new Set<string>();
|
|
118
|
-
this.addedToParent[scopeNode.name].add(rootPath);
|
|
119
|
-
|
|
120
127
|
scopeDataStructure.addEquivalency(
|
|
121
128
|
rootPath,
|
|
122
129
|
rootPath,
|
package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ScopeNode, ScopeDataStructure } from '../ScopeDataStructure';
|
|
|
6
6
|
|
|
7
7
|
type PrimitiveKind = 'array' | 'string' | 'number' | 'boolean' | 'date';
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const IGNORE_CLASSES_AND_OBJECTS_SET = new Set([
|
|
10
10
|
'Math',
|
|
11
11
|
'JSON',
|
|
12
12
|
'Reflect',
|
|
@@ -22,7 +22,7 @@ const IGNORE_CLASSES_AND_OBJECTS = [
|
|
|
22
22
|
'useContext',
|
|
23
23
|
'useReducer',
|
|
24
24
|
'useLayoutEffect',
|
|
25
|
-
];
|
|
25
|
+
]);
|
|
26
26
|
|
|
27
27
|
/** cache the tokenised representation of every path we touch */
|
|
28
28
|
const partsCache = new Map<string, string[]>();
|
|
@@ -147,16 +147,26 @@ function scrub(
|
|
|
147
147
|
rootTable: Map<string, PrimitiveKind>,
|
|
148
148
|
onRemove: (key: string) => void,
|
|
149
149
|
): void {
|
|
150
|
-
|
|
150
|
+
// Early exit: if no primitive types exist in the schema, there are no
|
|
151
|
+
// built-in methods to clean. Saves sorting + walking 10K+ keys.
|
|
152
|
+
if (rootTable.size === 0) return;
|
|
153
|
+
|
|
154
|
+
// Use direct comparison instead of localeCompare (3-5x faster for large arrays)
|
|
155
|
+
const sortedKeys = Object.keys(mapping).sort((a, b) =>
|
|
156
|
+
a < b ? -1 : a > b ? 1 : 0,
|
|
157
|
+
);
|
|
151
158
|
|
|
152
159
|
for (const keyPath of sortedKeys) {
|
|
153
160
|
const keyParts = getParts(keyPath);
|
|
154
161
|
const prefixParts = buildPrefixParts(keyParts);
|
|
155
162
|
|
|
163
|
+
const firstPart = keyParts[0];
|
|
164
|
+
const firstPartBase = firstPart.includes('(')
|
|
165
|
+
? firstPart.split('(')[0]
|
|
166
|
+
: firstPart;
|
|
156
167
|
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
)
|
|
168
|
+
IGNORE_CLASSES_AND_OBJECTS_SET.has(firstPart) ||
|
|
169
|
+
IGNORE_CLASSES_AND_OBJECTS_SET.has(firstPartBase)
|
|
160
170
|
) {
|
|
161
171
|
delete mapping[keyPath];
|
|
162
172
|
continue;
|
|
@@ -36,7 +36,10 @@ export { getAllEntityNodes } from './src/lib/asts/sourceFiles/getAllEntityNodes'
|
|
|
36
36
|
export { default as fileAnalyzerFromCode } from './src/lib/files/fileAnalyzerFromCode';
|
|
37
37
|
|
|
38
38
|
export { default as isolateDataStructure } from './src/lib/files/scenarios/isolateDataStructure';
|
|
39
|
-
export {
|
|
39
|
+
export {
|
|
40
|
+
default as mergeInDependentDataStructure,
|
|
41
|
+
DataStructureTimeoutError,
|
|
42
|
+
} from './src/lib/files/scenarios/mergeInDependentDataStructure';
|
|
40
43
|
export { default as mergeValidatedDataStructures } from './src/lib/files/scenarios/mergeValidatedDataStructures';
|
|
41
44
|
|
|
42
45
|
export { discoverDirectDependencies } from './src/lib/files/analyze/dependencyResolver';
|
|
@@ -289,18 +289,44 @@ export default async function prepareEntityDataStructures(
|
|
|
289
289
|
skipWorkerPool();
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
awsLogDebugLevel(
|
|
293
|
+
1,
|
|
294
|
+
`Preparing data structures for ${entities.length} entities (${entitiesNeedingGeneration} need generation)...`,
|
|
295
|
+
);
|
|
296
|
+
const startTime = Date.now();
|
|
297
|
+
let completedCount = 0;
|
|
298
|
+
|
|
299
|
+
// Wrap processEntity to track progress
|
|
300
|
+
const processEntityWithProgress = async (entity: Entity) => {
|
|
301
|
+
await processEntity(entity);
|
|
302
|
+
completedCount++;
|
|
303
|
+
// Emit progress every 10 entities
|
|
304
|
+
if (completedCount % 10 === 0) {
|
|
305
|
+
awsLogDebugLevel(
|
|
306
|
+
1,
|
|
307
|
+
`Preparing data structures... (${completedCount}/${entities.length})`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
292
312
|
const sequential =
|
|
293
313
|
DEBUG_SEQUENTIAL_EXECUTION || options.sequentialDataStructurePrep;
|
|
294
314
|
|
|
295
315
|
if (sequential) {
|
|
296
316
|
// Sequential execution for debugging - process one entity at a time
|
|
297
317
|
for (const entity of entities) {
|
|
298
|
-
await
|
|
318
|
+
await processEntityWithProgress(entity);
|
|
299
319
|
}
|
|
300
320
|
} else {
|
|
301
321
|
// Parallel execution for speed
|
|
302
|
-
await Promise.all(entities.map(
|
|
322
|
+
await Promise.all(entities.map(processEntityWithProgress));
|
|
303
323
|
}
|
|
324
|
+
|
|
325
|
+
const elapsed = Date.now() - startTime;
|
|
326
|
+
awsLogDebugLevel(
|
|
327
|
+
1,
|
|
328
|
+
`Data structure preparation complete: ${entities.length} entities in ${elapsed}ms`,
|
|
329
|
+
);
|
|
304
330
|
}
|
|
305
331
|
|
|
306
332
|
/**
|
|
@@ -8,13 +8,11 @@ import {
|
|
|
8
8
|
import { transformationTracer } from '../scenarios/TransformationTracer';
|
|
9
9
|
import { getFileByPathSafe } from '../../utils/getFileByPath';
|
|
10
10
|
import trackEntityCircularDependencies from './trackEntityCircularDependencies';
|
|
11
|
-
import validateDependencyAnalyses from './validateDependencyAnalyses';
|
|
12
11
|
import extractClassMethods from './analyzeEntities/extractClassMethods';
|
|
13
12
|
import prepareDataStructures from './analyzeEntities/prepareDataStructures';
|
|
14
13
|
import { strategies, asyncComplex } from './analyzeEntities/strategies';
|
|
15
14
|
import {
|
|
16
15
|
updateCommitMetadata,
|
|
17
|
-
updateFreshAnalysisMetadata,
|
|
18
16
|
updateFreshAnalysisStatus,
|
|
19
17
|
upsertAnalyses,
|
|
20
18
|
upsertEntities,
|
|
@@ -263,40 +261,11 @@ export default async function analyzeEntities({
|
|
|
263
261
|
}
|
|
264
262
|
}
|
|
265
263
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Validate dependencies, which modifies analysis.metadata.dependentAnalyses
|
|
275
|
-
validateDependencyAnalyses({ analysis, entity: analysis.entity, context });
|
|
276
|
-
|
|
277
|
-
// Carefully update only the metadata field
|
|
278
|
-
if (analysis.id) {
|
|
279
|
-
const updatedMetadata = await updateFreshAnalysisMetadata(
|
|
280
|
-
analysis.id,
|
|
281
|
-
(metadata) => {
|
|
282
|
-
metadata.dependentAnalyses =
|
|
283
|
-
analysis.metadata?.dependentAnalyses || [];
|
|
284
|
-
},
|
|
285
|
-
);
|
|
286
|
-
|
|
287
|
-
if (updatedMetadata) {
|
|
288
|
-
analysis.metadata = updatedMetadata;
|
|
289
|
-
} else {
|
|
290
|
-
console.warn(
|
|
291
|
-
`CodeYam: analyzeEntities: Failed to update metadata for analysis ${analysis.id}`,
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
console.warn(
|
|
296
|
-
`CodeYam: analyzeEntities: Analysis ${analysis.filePath}:${analysis.entityName} has no ID, skipping metadata update`,
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
264
|
+
// NOTE: patch-up dependency validation loop was removed here.
|
|
265
|
+
// analysis.metadata.dependentAnalyses is already populated by validateDependencyAnalyses
|
|
266
|
+
// inside analyzeEntity() (Call #1) and persisted via upsertAnalysesWithScenarios at the
|
|
267
|
+
// end of analyzeEntity, then again by upsertAnalyses in analyzeOneEntityKey. Re-validating
|
|
268
|
+
// every analysis from scratch was redundant work — especially costly for large projects.
|
|
300
269
|
|
|
301
270
|
const newlyReady = await updateReadyAnalyses();
|
|
302
271
|
if (newlyReady.length > 0) {
|
package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Entity } from '~codeyam/types';
|
|
2
2
|
import { AnalysisContext } from '../../analysisContext';
|
|
3
|
+
import { awsLogDebugLevel } from '~codeyam/utils';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Optimized version that processes multiple root entities in a single traversal.
|
|
@@ -16,6 +17,8 @@ export default function trackEntityCircularDependencies(
|
|
|
16
17
|
try {
|
|
17
18
|
const allEntities = new Set<Entity>();
|
|
18
19
|
const globalVisited = new Set<string>(); // Track by SHA to avoid duplicate traversals
|
|
20
|
+
let circularCount = 0;
|
|
21
|
+
const startTime = Date.now();
|
|
19
22
|
|
|
20
23
|
// Process each root entity, but skip if already processed
|
|
21
24
|
for (const rootEntity of rootEntities) {
|
|
@@ -32,8 +35,26 @@ export default function trackEntityCircularDependencies(
|
|
|
32
35
|
globalVisited,
|
|
33
36
|
allEntities,
|
|
34
37
|
);
|
|
38
|
+
|
|
39
|
+
// Emit periodic progress for large projects
|
|
40
|
+
if (allEntities.size % 100 === 0 && allEntities.size > 0) {
|
|
41
|
+
awsLogDebugLevel(
|
|
42
|
+
1,
|
|
43
|
+
`Mapping dependencies... (${allEntities.size} entities discovered)`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
35
46
|
}
|
|
36
47
|
|
|
48
|
+
const elapsed = Date.now() - startTime;
|
|
49
|
+
// Count circular deps
|
|
50
|
+
for (const entity of allEntities) {
|
|
51
|
+
if (entity.metadata?.hasCircularDependency) circularCount++;
|
|
52
|
+
}
|
|
53
|
+
awsLogDebugLevel(
|
|
54
|
+
1,
|
|
55
|
+
`Dependency mapping complete: ${allEntities.size} entities, ${circularCount} circular, ${elapsed}ms`,
|
|
56
|
+
);
|
|
57
|
+
|
|
37
58
|
return allEntities;
|
|
38
59
|
} catch (e) {
|
|
39
60
|
console.log(
|
package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts
CHANGED
|
@@ -6,6 +6,20 @@ import type {
|
|
|
6
6
|
ReadonlyEntity,
|
|
7
7
|
} from '~codeyam/types';
|
|
8
8
|
import { ImmutableAnalysisContext } from '../../analysisContext';
|
|
9
|
+
import { awsLogDebugLevel } from '~codeyam/utils';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Tracks statistics across the recursive dependency validation.
|
|
13
|
+
* Shared by all recursive calls to provide a complete picture.
|
|
14
|
+
*/
|
|
15
|
+
interface ValidationStats {
|
|
16
|
+
totalVisited: number;
|
|
17
|
+
skippedDuplicate: number;
|
|
18
|
+
skippedMissing: number;
|
|
19
|
+
skippedTrivial: number;
|
|
20
|
+
maxDepth: number;
|
|
21
|
+
startTime: number;
|
|
22
|
+
}
|
|
9
23
|
|
|
10
24
|
export default function validateDependencyAnalyses({
|
|
11
25
|
analysis,
|
|
@@ -13,12 +27,18 @@ export default function validateDependencyAnalyses({
|
|
|
13
27
|
entity,
|
|
14
28
|
context,
|
|
15
29
|
dependentAnalyses,
|
|
30
|
+
_depth = 0,
|
|
31
|
+
_stats,
|
|
16
32
|
}: {
|
|
17
33
|
analysis?: Analysis;
|
|
18
34
|
readonlyAnalysis?: ReadonlyAnalysis;
|
|
19
35
|
entity: ReadonlyEntity;
|
|
20
36
|
context: ImmutableAnalysisContext;
|
|
21
37
|
dependentAnalyses?: ReadonlyAnalysisMap;
|
|
38
|
+
/** Recursion depth (internal, do not set) */
|
|
39
|
+
_depth?: number;
|
|
40
|
+
/** Shared stats tracker (internal, do not set) */
|
|
41
|
+
_stats?: ValidationStats;
|
|
22
42
|
}): { dependentAnalyses: ReadonlyAnalysisMap } {
|
|
23
43
|
if (!readonlyAnalysis) readonlyAnalysis = analysis;
|
|
24
44
|
if (!readonlyAnalysis) {
|
|
@@ -32,6 +52,28 @@ export default function validateDependencyAnalyses({
|
|
|
32
52
|
);
|
|
33
53
|
}
|
|
34
54
|
|
|
55
|
+
// Initialize stats on the root call
|
|
56
|
+
const isRootCall = _depth === 0;
|
|
57
|
+
if (!_stats) {
|
|
58
|
+
_stats = {
|
|
59
|
+
totalVisited: 0,
|
|
60
|
+
skippedDuplicate: 0,
|
|
61
|
+
skippedMissing: 0,
|
|
62
|
+
skippedTrivial: 0,
|
|
63
|
+
maxDepth: 0,
|
|
64
|
+
startTime: Date.now(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (_depth > _stats.maxDepth) _stats.maxDepth = _depth;
|
|
68
|
+
|
|
69
|
+
const importCount = entity.metadata?.importedExports?.length ?? 0;
|
|
70
|
+
if (isRootCall && importCount > 0) {
|
|
71
|
+
awsLogDebugLevel(
|
|
72
|
+
2,
|
|
73
|
+
`validateDeps: ${entity.name} has ${importCount} imports to validate`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
35
77
|
if (
|
|
36
78
|
dependentAnalyses &&
|
|
37
79
|
dependentAnalyses[readonlyAnalysis.filePath]?.[
|
|
@@ -45,6 +87,12 @@ export default function validateDependencyAnalyses({
|
|
|
45
87
|
})
|
|
46
88
|
) {
|
|
47
89
|
// already processed this analysis
|
|
90
|
+
if (isRootCall) {
|
|
91
|
+
awsLogDebugLevel(
|
|
92
|
+
2,
|
|
93
|
+
`validateDeps: ${entity.name} already fully processed (cache hit)`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
48
96
|
return { dependentAnalyses };
|
|
49
97
|
}
|
|
50
98
|
|
|
@@ -69,9 +117,20 @@ export default function validateDependencyAnalyses({
|
|
|
69
117
|
|
|
70
118
|
// if the entity has duplicate dependencies, handle gracefully
|
|
71
119
|
if (dependentAnalyses[dependencyFilePath]?.[dependencyName]) {
|
|
120
|
+
_stats.skippedDuplicate++;
|
|
72
121
|
continue;
|
|
73
122
|
}
|
|
74
123
|
|
|
124
|
+
_stats.totalVisited++;
|
|
125
|
+
|
|
126
|
+
// Emit periodic progress so the spinner stays alive for large trees
|
|
127
|
+
if (_stats.totalVisited % 50 === 0) {
|
|
128
|
+
awsLogDebugLevel(
|
|
129
|
+
1,
|
|
130
|
+
`Validating dependencies... (${_stats.totalVisited} resolved, depth ${_depth})`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
75
134
|
// Check if dependency analysis exists in context
|
|
76
135
|
const dependentAnalysis = context.getAnalysis(
|
|
77
136
|
dependencyFilePath,
|
|
@@ -86,21 +145,20 @@ export default function validateDependencyAnalyses({
|
|
|
86
145
|
);
|
|
87
146
|
|
|
88
147
|
if (!dependentEntity) {
|
|
89
|
-
|
|
90
|
-
// `CodeYam: validateDependencyAnalyses: Missing dependent entity ${dependencyFilePath}:${dependencyName} for ${entity.filePath}:${entity.name}. This is likely a bug.`,
|
|
91
|
-
// );
|
|
148
|
+
_stats.skippedMissing++;
|
|
92
149
|
continue;
|
|
93
150
|
}
|
|
94
151
|
|
|
95
152
|
// ignore trivial missing dependencies
|
|
96
|
-
if (!['library', 'visual'].includes(dependentEntity.entityType))
|
|
153
|
+
if (!['library', 'visual'].includes(dependentEntity.entityType)) {
|
|
154
|
+
_stats.skippedTrivial++;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
97
157
|
|
|
98
158
|
if (!dependentEntity?.metadata?.hasCircularDependency) {
|
|
99
159
|
// TODO: This no longer seems to happen thanks to fixes elsewhere, but leave the warning
|
|
100
|
-
// console.warn(
|
|
101
|
-
// `CodeYam: validateDependencyAnalyses: Missing analysis for dependency ${entity.filePath}:${entity.name} -> ${dependencyFilePath}:${dependencyName}, should be marked as having circular dependencies.`,
|
|
102
|
-
// );
|
|
103
160
|
}
|
|
161
|
+
_stats.skippedMissing++;
|
|
104
162
|
continue;
|
|
105
163
|
}
|
|
106
164
|
|
|
@@ -136,9 +194,6 @@ export default function validateDependencyAnalyses({
|
|
|
136
194
|
if (analysis) {
|
|
137
195
|
// Track dependency relationship in analysis metadata
|
|
138
196
|
if (!analysis.metadata.dependentAnalyses.includes(dependentAnalysis.id)) {
|
|
139
|
-
// console.log(
|
|
140
|
-
// `CodeYam: validateDependencyAnalyses: Establishing dependency ${analysis.filePath}:${analysis.entityName} -> ${dependentAnalysis.filePath}:${dependentAnalysis.entityName}.`,
|
|
141
|
-
// );
|
|
142
197
|
analysis.metadata.dependentAnalyses.push(dependentAnalysis.id);
|
|
143
198
|
}
|
|
144
199
|
}
|
|
@@ -152,9 +207,26 @@ export default function validateDependencyAnalyses({
|
|
|
152
207
|
entity: dependentEntity,
|
|
153
208
|
context: context,
|
|
154
209
|
dependentAnalyses,
|
|
210
|
+
_depth: _depth + 1,
|
|
211
|
+
_stats,
|
|
155
212
|
});
|
|
156
213
|
}
|
|
157
214
|
}
|
|
158
215
|
|
|
216
|
+
// Log summary on root call completion
|
|
217
|
+
if (isRootCall) {
|
|
218
|
+
const elapsed = Date.now() - _stats.startTime;
|
|
219
|
+
const totalDeps = Object.values(dependentAnalyses).reduce(
|
|
220
|
+
(sum, fileMap) => sum + Object.keys(fileMap).length,
|
|
221
|
+
0,
|
|
222
|
+
);
|
|
223
|
+
awsLogDebugLevel(
|
|
224
|
+
1,
|
|
225
|
+
`Dependency validation complete for ${entity.name}: ${totalDeps} dependencies resolved, ` +
|
|
226
|
+
`${_stats.skippedDuplicate} duplicates skipped, ${_stats.skippedMissing} missing, ` +
|
|
227
|
+
`${_stats.skippedTrivial} trivial, max depth ${_stats.maxDepth}, ${elapsed}ms`,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
159
231
|
return { dependentAnalyses };
|
|
160
232
|
}
|
|
@@ -91,6 +91,10 @@ export default async function analyzeChange({
|
|
|
91
91
|
// Structure phase: CPU-intensive, serialize via semaphore if provided
|
|
92
92
|
if (!steps || steps.includes(Step.Structure)) {
|
|
93
93
|
if (structureSemaphore) {
|
|
94
|
+
awsLogDebugLevel(
|
|
95
|
+
1,
|
|
96
|
+
`Waiting for structure semaphore for ${entity.name}...`,
|
|
97
|
+
);
|
|
94
98
|
await structureSemaphore.acquire();
|
|
95
99
|
}
|
|
96
100
|
try {
|
|
@@ -58,6 +58,10 @@ export default async function analyzeInitial({
|
|
|
58
58
|
// Structure phase: CPU-intensive, serialize via semaphore if provided
|
|
59
59
|
if (!steps || steps.includes(Step.Structure)) {
|
|
60
60
|
if (structureSemaphore) {
|
|
61
|
+
awsLogDebugLevel(
|
|
62
|
+
1,
|
|
63
|
+
`Waiting for structure semaphore for ${entity.name}...`,
|
|
64
|
+
);
|
|
61
65
|
await structureSemaphore.acquire();
|
|
62
66
|
}
|
|
63
67
|
try {
|
|
@@ -3,6 +3,8 @@ import { ProjectAnalyzer } from '../ProjectAnalyzer';
|
|
|
3
3
|
import { generateSha } from '~codeyam/database';
|
|
4
4
|
import { isNextRoute } from '~codeyam/utils';
|
|
5
5
|
|
|
6
|
+
const warnedLayoutPaths = new Set<string>();
|
|
7
|
+
|
|
6
8
|
export default function analyzeNextRoute(
|
|
7
9
|
file: File,
|
|
8
10
|
projectAnalyzer: ProjectAnalyzer,
|
|
@@ -56,9 +58,12 @@ export default function analyzeNextRoute(
|
|
|
56
58
|
|
|
57
59
|
// Ensure entities array exists before trying to use it
|
|
58
60
|
if (!layout.entities) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
if (!warnedLayoutPaths.has(layout.path)) {
|
|
62
|
+
warnedLayoutPaths.add(layout.path);
|
|
63
|
+
console.log(
|
|
64
|
+
`CodeYam Warning: layout.entities not populated for ${layout.path}, skipping implicit dependency`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
69
|
|